/* 文件属性与目录 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> 
#include <sys/stat.h> 
#include <unistd.h> 
#include <time.h> 
#include <dirent.h> 
#include <errno.h>

int main()
{
    FILE *fd = NULL;
    int fa;
    int count = 0;
    struct stat fp;
    struct tm file_tm; 
    char time_str[100];

    fd = fopen("./testapp.txt","w+"); 
    if(fd == NULL) {
        perror("creat error");
        exit(-1);
    } printf("creat success\n");

    //创建硬连接
    if(link("./testapp.txt","test-hard") < 0) {
        perror("link error");
        fclose(fd);
        exit(-1);
    } printf("link success\n");
    //创建软连接  可以使用 readlink 读取软链接文件，提取指向的文件路径
    if(symlink("./testapp.txt","test-soft") < 0) {
        perror("symlink error");
        fclose(fd);
        exit(-1);
    } printf("symlink success\n");

    count = fwrite("当前路径：/home/wx/Desktop/C-application/25.7.24",1,53,fd);
    if(count < 53) {
        if(ferror(fd)) {
            printf("write error\n");
            fclose(fd);
            exit(-1);
        }
    } printf("成功写入: %d byte\n",count);

    // 获取文件描述符
    fa=fileno(fd);
    if(fa < 0) {
        perror("转换失败");
        fclose(fd);
        exit(-1);
    } printf("转换成功\n");

    //将用户空间缓冲区的数据刷新到内核缓冲区
    if(fflush(fd) != 0) {
        perror("fflush error");
        fclose(fd);
        exit(-1);
    }
    printf("fflush success\n");

    // 同步文件到磁盘
    if(fsync(fa) < 0) {
        perror("fsync error");
        fclose(fd);
        exit(-1);
    } printf("fsync success\n");

    // 获取文件属性
    if(0 > stat("./testapp.txt",&fp)) {
        perror("stat error");
        exit(-1);
    } printf("stat success\n");
    
    // 输出文件属性
    printf("inode: %ld\n",fp.st_ino);
    printf("size: %ld\n",fp.st_size);

    switch (fp.st_mode & S_IFMT) { 
        case S_IFSOCK: printf("套接字文件\n"); break; 
        case S_IFLNK: printf("链接文件\n"); break; 
        case S_IFREG: printf("普通文件\n"); break; 
        case S_IFBLK: printf("块设备文件\n"); break; 
        case S_IFDIR: printf("目录文件\n"); break; 
        case S_IFCHR: printf("字符设备文件\n"); break; 
        case S_IFIFO: printf("管道文件\n"); break; 
        default: break;
    } 

    // 检查权限
    if(fp.st_mode & S_IWOTH) {
        printf("Other 有写权限\n");
    }
    else {
        printf("Other 无写权限\n");
    }
    if(fp.st_mode & S_IROTH) {
        printf("Other 有读权限\n");
    }
    else {
        printf("Other 无读权限\n");
    }

    /* 打印文件最后被访问的时间 */ 
    localtime_r(&fp.st_atim.tv_sec, &file_tm); 
    strftime(time_str, sizeof(time_str), 
                "%Y-%m-%d %H:%M:%S", &file_tm); 
    printf("time of last access: %s\n", time_str); 
 
    /* 打印文件内容最后被修改的时间 */ 
    localtime_r(&fp.st_mtim.tv_sec, &file_tm); 
    strftime(time_str, sizeof(time_str), 
                "%Y-%m-%d %H:%M:%S", &file_tm);
    printf("time of last modification: %s\n", time_str); 
    /* 打印文件状态最后改变的时间 */ 
    localtime_r(&fp.st_ctim.tv_sec, &file_tm); 
    strftime(time_str, sizeof(time_str), 
    "%Y-%m-%d %H:%M:%S", &file_tm); 
    printf("time of last status change: %s\n", time_str); 

    fclose(fd);

    //文件夹操作
    struct dirent *dir = NULL;
    DIR *dirp;
    /* 打开文件夹 */
    dirp = opendir(".");
    if(dirp == NULL) {
        perror("opendir error");
        exit(-1);
    } printf("\n");

    /* 循环读目录流中所有目录条目 */
    errno = 0;

    while((dir = readdir(dirp)) != NULL) {
        printf("%ld %s\n",dir->d_ino,dir->d_name);
    }
    if(errno != 0) {
            perror("readdir error");
            closedir(dirp);
            exit(-1);
    }
    else {
        printf("End of directory\n");
    }
    closedir(dirp);

    char buff[50] = {0};
    char *ptr = NULL;
    ptr = getcwd(buff,sizeof(buff));
    if(ptr == NULL) {
        perror("getcwd error");
        exit(-1);
    } printf("Current working directory: %s\n",ptr);
    printf("buff: %s\n",buff);  /* buff 中存放的也是当前进程工作目录 */
    
    return 0;
}